/* This module remaps the interrupts. The idiot PPC is limitted to a window
   that is a multiple of 64K, so we cannot map it into block RAM. The EVPR is
   loaded with OPB_INTERRUPT_MAP (x70010000) and this module provides instructions 
   at these addresses to handle various interrupts.

    Critical-Input Interrupt              EVPR + 32'h0100
    Machine-Check Interrupt               EVPR + 32'h0200
    Data-Storage Interrupt                EVPR + 32'h0300
    Instruction-Storage Interrupt         EVPR + 32'h0400
    External Interrupt                    EVPR + 32'h0500
    Alignment Interrupt                   EVPR + 32'h0600
    Program Interrupt                     EVPR + 32'h0700
    FPU-Unavailable Interrupt             EVPR + 32'h0800
    System-Call Interrupt                 EVPR + 32'h0C00
    APU-Unavailable Interrupt             EVPR + 32'h0F20
    Programmable-Interval Timer Interrupt EVPR + 32'h1000
    Fixed-Interval Timer Interrupt        EVPR + 32'h1010
    Watchdog-Timer Interrupt              EVPR + 32'h1020
    Data TLB-Miss Interrupt               EVPR + 32'h1100
    Instruction TLB-Miss Interrupt        EVPR + 32'h1200
    Debug Interrupt                       EVPR + 32'h2000

   Copyright 2007, Pico Computing, Inc.
*/
`include "PicoDefines.v"

module INTERRUPT_MAPPER
 (input  [31:0]OPB_ABus,//     "
  input  OPB_RNW,       //     "
  output [31:0]Sl_DBus, //Slave -> OPB Signals
  output Sl_errAck,     //     "
  output Sl_retry,      //     "
  output Sl_toutSup,    //     "
  output Sl_xferAck     //     "
 );

wire MachineCheckIntr             = OPB_RNW & {OPB_ABus[31:2], 2'b0} == (`OPB_INTERRUPT_MAP +32'h0200);
`ifdef NEVER
wire CriticalInputIntr            = OPB_RNW & {OPB_ABus[31:2], 2'b0} == (`OPB_INTERRUPT_MAP +32'h0100);
wire DataStorageIntr              = OPB_RNW & {OPB_ABus[31:2], 2'b0} == (`OPB_INTERRUPT_MAP +32'h0300);
wire InstructionStorageIntr       = OPB_RNW & {OPB_ABus[31:2], 2'b0} == (`OPB_INTERRUPT_MAP +32'h0400);
wire ExternalIntr                 = OPB_RNW & {OPB_ABus[31:2], 2'b0} == (`OPB_INTERRUPT_MAP +32'h0500);
wire AlignmentIntr                = OPB_RNW & {OPB_ABus[31:2], 2'b0} == (`OPB_INTERRUPT_MAP +32'h0600);
wire ProgramIntr                  = OPB_RNW & {OPB_ABus[31:2], 2'b0} == (`OPB_INTERRUPT_MAP +32'h0700);
wire FPU_UnavailableIntr          = OPB_RNW & {OPB_ABus[31:2], 2'b0} == (`OPB_INTERRUPT_MAP +32'h0800);
wire SystemCallIntr               = OPB_RNW & {OPB_ABus[31:2], 2'b0} == (`OPB_INTERRUPT_MAP +32'h0C00);
wire APUunavailableIntr           = OPB_RNW & {OPB_ABus[31:2], 2'b0} == (`OPB_INTERRUPT_MAP +32'h0F20);
wire ProgrammableIntervalTimerIntr= OPB_RNW & {OPB_ABus[31:2], 2'b0} == (`OPB_INTERRUPT_MAP +32'h1000);
wire FixedIntervalTimerIntr       = OPB_RNW & {OPB_ABus[31:2], 2'b0} == (`OPB_INTERRUPT_MAP +32'h1010);
wire WatchdogTimerIntr            = OPB_RNW & {OPB_ABus[31:2], 2'b0} == (`OPB_INTERRUPT_MAP +32'h1020);
wire DataTLB_MissIntr             = OPB_RNW & {OPB_ABus[31:2], 2'b0} == (`OPB_INTERRUPT_MAP +32'h1100);
wire InstructionTLB_MissIntr      = OPB_RNW & {OPB_ABus[31:2], 2'b0} == (`OPB_INTERRUPT_MAP +32'h1200);
`endif
wire DebugIntr                    = OPB_RNW & {OPB_ABus[31:2], 2'b0} == (`OPB_INTERRUPT_MAP +32'h2000);

assign Sl_retry      = 0;
assign Sl_errAck     = 0;
assign Sl_toutSup    = 0; 
assign Sl_xferAck    = OPB_RNW & {OPB_ABus[31:16], 16'b0} == `OPB_INTERRUPT_MAP; //any of these signals

assign Sl_DBus[31:0] = (DebugIntr        ? 32'h4C000066 : 32'h0) | //something useful would be nice
                       (MachineCheckIntr ? 32'h4C000066 : 32'h0);  //rfci instruction

endmodule